using System;
using System.Runtime.InteropServices;
using System.Text;

namespace NTrace
{
  internal static partial class NativeMethods
  {
    internal const long InvalidHandle = -1;
    internal const uint Success = 0;
    /// <summary>
    /// Implement this delegate to receive enable or disable notification requests from controllers.
    /// </summary>
    /// <param name="enableState"></param>
    /// <param name="context">Provider-defined context.</param>
    /// <param name="reserved">Reserved for internal use.</param>
    /// <param name="buffer"></param>
    /// <returns></returns>
    internal delegate int ControlCallback(
      TraceEnableState enableState,
      IntPtr context,
      IntPtr reserved,
      TraceHeader buffer
    );

    /// <summary>
    /// Registers an event trace provider and the event trace classes that it uses to generate
    /// events. This function also specifies the function the provider uses to enable and
    /// disable tracing.
    /// </summary>
    /// <param name="requestAddress">
    /// Pointer to a ControlCallback function that receives notification when the provider is
    /// enabled or disabled by an event tracing session. The EnableTrace function calls the
    /// callback.
    /// </param>
    /// <param name="requestContext">
    /// Pointer to an optional provider-defined context that ETW passes to the function
    /// specified by <paramref name="requestAddress"/>.
    /// </param>
    /// <param name="controlGuid">
    /// GUID of the registering provider.
    /// </param>
    /// <param name="guidCount">
    /// Number of elements in the TraceGuidReg array. If TraceGuidReg is NULL, set this
    /// parameter to 0.
    /// </param>
    /// <param name="traceGuidReg">
    /// Pointer to an array of <see cref="TraceGuidRegistration"/> structures. Each element
    /// identifies a category of events that the provider provides.
    /// </param>
    /// <param name="mofImagePath">This parameter is not supported, set to <b>null</b>.</param>
    /// <param name="mofResourceName">This parameter is not supported, set to <b>null</b>.</param>
    /// <param name="registrationHandle">
    /// Pointer to the provider's registration handle. Use this handle when you call the
    /// <see cref="UnregisterTraceGuids"/> function.</param>
    /// <returns></returns>
    [DllImport("AdvApi32", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern int RegisterTraceGuids(
        ControlCallback requestAddress,
        IntPtr requestContext,
        ref Guid controlGuid,
        int guidCount,
        ref TraceGuidRegistration traceGuidReg,
        String mofImagePath,
        String mofResourceName,
        out ulong registrationHandle);

    /// <summary>
    /// Unregisters an event trace provider and its event trace classes. 
    /// </summary>
    /// <param name="registrationHandle">
    /// Handle to the event trace provider, obtained from an earlier call to the 
    /// <see cref="RegisterTraceGuids"/> function.
    /// </param>
    /// <returns></returns>
    [DllImport("AdvApi32", SetLastError = true)]
    internal static extern int UnregisterTraceGuids(
        ulong registrationHandle);

    /// <summary>
    /// Retrieves the handle of the event tracing session.
    /// </summary>
    /// <param name="sessionHandle">
    /// Handle to an event tracing session, obtained by calling the GetTraceLoggerHandle function.
    /// </param>
    /// <returns>The event tracing session handle, .</returns>
    /// <remarks>Providers can only call this function from their ControlCallback function.</remarks>
    [DllImport("AdvApi32", SetLastError = true)]
    internal static extern ulong GetTraceLoggerHandle(TraceHeader header);

    /// <summary>
    /// Retrieves the enable flags passed by the controller to indicate which category of events to trace.
    /// </summary>
    /// <param name="sessionHandle">
    /// Handle to an event tracing session, obtained by calling the GetTraceLoggerHandle function.
    /// </param>
    /// <returns>A flag bitfield.</returns>
    /// <remarks>Providers can only call this function from their ControlCallback function.</remarks>
    [DllImport("AdvApi32", SetLastError = true)]
    internal static extern uint GetTraceEnableFlags(ulong sessionHandle);

    /// <summary>
    /// Retrieves the severity level passed by the controller to indicate the level of logging the provider should perform.
    /// </summary>
    /// <param name="sessionHandle">
    /// Handle to an event tracing session, obtained by calling the GetTraceLoggerHandle function.
    /// </param>
    /// <returns>A level bitfield.</returns>
    /// <remarks>Providers can only call this function from their ControlCallback function.</remarks>
    [DllImport("AdvApi32", SetLastError = true)]
    internal static extern byte GetTraceEnableLevel(ulong sessionHandle);

    /// <summary>
    /// Sends an event to an event tracing session. 
    /// </summary>
    /// <param name="sessionHandle">
    /// Handle to the event tracing session that records the event.
    /// </param>
    /// <param name="eventTrace">
    /// A pointer to an <see cref="EventTraceHeader"/>.
    /// </param>
    /// <returns></returns>
    [DllImport("AdvApi32")]
    internal static extern TraceEventErrorCode TraceEvent(
        ulong sessionHandle,
        IntPtr eventTrace);

    /// <summary>
    /// Moves a pointer to unmnaged memory
    /// </summary>
    /// <param name="pointer">An <see cref="System.IntPtr"/> pointing to a block of allocated memory.</param>
    /// <param name="bytes">An <see cref="System.Int32"/> containing the number of bytes to move the pointer.</param>
    /// <returns>A <see cref="System.IntPtr"/> pointing to the new location.</returns>
    internal static IntPtr MovePointer(IntPtr pointer, int bytes)
    {
      return (IntPtr)((long)pointer + bytes);
    }
  }
}
